/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-06-10     Administrator       the first version
 */
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include <ina226.h>



#define INA226_I2C_BUS    "i2c2"      // I2C总线名称
static struct rt_i2c_bus_device *i2c_bus = RT_NULL;
//#define INA226_I2C_ADDR   0x40  /* INA226 I2C 地址 */

//#include "stm32f10x.h"                  // Device header
//#include "MyI2C.h"

/*IIC 地址---------------------------------------------------------------------------------------------*/
#define INA226_W 0x80
#define INA226_R 0x81
/*寄存器地址--------------------------------------------------------------------------------------------*/
#define INA226_Configuration                          0x00
#define INA226_Shuntvoltage                           0x01
#define INA226_Busvoltage                             0x02
#define INA226_Power                                  0x03
#define INA226_Current                                0x04
#define INA226_Calibration                            0x05
#define INA226_Mask                                   0x06
#define INA226_AlertLimit                             0x07
#define INA226_ManufacturerID                         0xFE
#define INA226_DieID                                  0xFF
/* INA226_curation Bit15-0 --------------------------------------------------------------------------*/
#define RST                     0       // 0   设置成1复位 （Bit15）
#define Reservation       0x04  // 100 （Bit14-12 保留）
#define AVG                             0x01  // 001 平均次数 4 （Bit11-9）
#define VBUSCT                      0x04    // 100 总线电压转换时间 1.1ms （Bit116-8）
#define VSHCT                       0x04    // 100 分流电压转换时间 1.1ms（Bit3-5）
#define MODE                0x07    // 111 运行模式  连续检测（默认）（Bit0–2）

#define Configuration_H (RST << 7)|(Reservation << 4)|(AVG << 1)|(VBUSCT >> 2)
#define Configuration_L ((VBUSCT & 0x03) << 6)|(VSHCT << 3)|(MODE)

/* INA226_Calibration ---------------------------------------------------------------------------------*/
//#define Calibration_H 0x04
//#define Calibration_L 0x00

//MAX_Current = Full-scale range / R·SHUNT = 81.92mV / 0.1R = 819.2mA
//Current_LSB = 819.2mA / 2^15 = 0.025mA
//选择接近值：0.05mA = 0.00005A 手册推荐1mA 但是便于CAL计算和实际调试则重新选择为 0.05mA
//(手册：While this value yields the highest resolution, it is common to select a value for the Current_LSB to the nearest round number above this value to simplify the conversion of the Current Register (04h) and Power Register (03h) to amperes and watts respectively.)
//(虽然该值产生最高分辨率，但通常为Current_LSB选择一个值，使其与高于该值的最接近的整数相匹配，以简化电流寄存器（04h）和功率寄存器（03h）分别转换为安培和瓦的过程。)
//CAL = 0.00512 / (Current_LSB * R·SHUNT) = 0.00512 / (0.00005A * 0.1R) = 1024 = 0x0400
//Power_LSB = Current_LSB * 25 = 0.05mA * 25 = 1.25mW
//(手册：The power LSB has a fixed ratio to the Current_LSB of 25)
//(power LSB与Current_LSB的固定比率为25)

#define Calibration_H 0x03
#define Calibration_L 0xC5
//实测发现电流偏大，采用手册校准公式 Corrected_Full_Scale_Cal = (Cal * MeasShuntCurrent) / INA226_Current
//5V 测试条件下 MeasShuntCurrent = 490 mV   INA226_Current = 520mV  Corrected_Full_Scale_Cal = 490 * 1024 / 520 = 964.9 = 965 = 0x03C5
void INA226_WriteReg(uint8_t Register, uint8_t Data_H, uint8_t Data_L)
{
/*
    MyI2C_Start();                        //I2C起始
    MyI2C_SendByte(INA226_W);     //发送从机地址，读写位为0，表示即将写入
    MyI2C_ReceiveAck();                 //接收应答
    MyI2C_SendByte(Register);       //发送寄存器地址
    MyI2C_ReceiveAck();                 //接收应答
    MyI2C_SendByte(Data_H);         //发送要写入寄存器的数据高位
    MyI2C_ReceiveAck();                 //接收应答
    MyI2C_SendByte(Data_L);         //发送要写入寄存器的数据低位
    MyI2C_ReceiveAck();                 //接收应答
    MyI2C_Stop();                           //I2C终止
*/
    rt_uint8_t buf[3];
    struct rt_i2c_msg msgs;

    buf[0] = Register;
    buf[1] = Data_H;   // 高字节
    buf[2] = Data_L; // 低字节

    msgs.addr  = INA226_W;
    msgs.flags = RT_I2C_WR;
    msgs.buf   = buf;
    msgs.len   = 3;

    if (rt_i2c_transfer(i2c_bus, &msgs, 1) == 1) {
        return RT_EOK;
    }

}
uint32_t INA226_ReadReg(uint8_t RegAddress,rt_uint16_t *value)
{
/*    uint32_t Data;

    MyI2C_Start();                        //I2C起始
    MyI2C_SendByte(INA226_W);     //发送从机地址
    MyI2C_ReceiveAck();                 //接收应答
    MyI2C_SendByte(RegAddress); //发送寄存器地址
    MyI2C_ReceiveAck();                 //接收应答

    MyI2C_Start();                      //I2C重复起始
    MyI2C_SendByte(INA226_R);     //发送从机地址
    MyI2C_ReceiveAck();                 //接收应答
    Data = MyI2C_ReceiveByte(); //接收指定寄存器的高位数据
    MyI2C_SendAck(0);                   //发送应答
    Data = (Data << 8)| MyI2C_ReceiveByte();    //接收指定寄存器的低位数据
    MyI2C_Stop();                           //I2C终止

    return Data;*/


    rt_uint8_t buf[2];
    struct rt_i2c_msg msgs[2];

    /* 发送寄存器地址 */
    msgs[0].addr  = INA226_W;
    msgs[0].flags = RT_I2C_WR;
    msgs[0].buf   = &RegAddress;
    msgs[0].len   = 1;

    /* 读取数据 */
    msgs[1].addr  = INA226_R;
    msgs[1].flags = RT_I2C_RD;
    msgs[1].buf   = buf;
    msgs[1].len   = 2;

    if (rt_i2c_transfer(i2c_bus, msgs, 2) == 2) {
        *value = (buf[0] << 8) | buf[1];
        return RT_EOK;
    }

    return -RT_ERROR;
}
void INA226_Init(void)
{
    INA226_WriteReg(INA226_Configuration,Configuration_H,Configuration_L);   //4次平均  1.1ms转换时间  连续检测
    INA226_WriteReg(INA226_Calibration,Calibration_H,Calibration_L);         //基准值 0x0200
}
uint32_t INA226_GetShuntVoltage(void)//分流电压值 =  寄存器值 * LSB(2.5uA)
{
/*    uint32_t ShuntVoltage;
    ShuntVoltage = (uint32_t)((INA226_ReadReg(INA226_Shuntvoltage)) * 2.5 / 1000);

    return ShuntVoltage;*/
    rt_uint16_t raw;
    if (INA226_ReadReg(INA226_Shuntvoltage, &raw) == RT_EOK) {
        // 处理有符号值
        rt_int16_t signed_raw = (rt_int16_t)raw;
        // 电流计算: Current = raw * current_lsb
        return signed_raw * 2.5 * 1000.0f; // 转换为mA
    }
    return 0.0f;
}
uint32_t INA226_GetBusVoltage(void)//总线电压值 =  寄存器值 * LSB(1.25mV)
{
/*    uint32_t BusVoltage;
    BusVoltage = (uint32_t)((INA226_ReadReg(INA226_Busvoltage)) * 1.25);

    return BusVoltage;*/
    rt_uint16_t raw;
    if (INA226_ReadReg(INA226_Busvoltage, &raw) == RT_EOK) {
        // 处理有符号值
        rt_int16_t signed_raw = (rt_int16_t)raw;
        // 电流计算: Current = raw * current_lsb
        return signed_raw * 1.25 * 1000.0f; // 转换为mA
    }
    return 0.0f;
}
uint32_t INA226_GetCurrent(void)//电流值 = 寄存器值 * Current_LSB(0.05mA)
{
/*    uint32_t Current;
    Current = (uint32_t)((INA226_ReadReg(INA226_Current)) * 0.05);

    return Current;*/
    rt_uint16_t raw;

    if (INA226_ReadReg(INA226_Current, &raw) == RT_EOK) {
        // 处理有符号值
        rt_int16_t signed_raw = (rt_int16_t)raw;
        // 电流计算: Current = raw * current_lsb
        return signed_raw * 0.05 * 1000.0f; // 转换为mA
    }
    return 0.0f;
}
uint32_t INA226_GetPower(void)//功率 = 寄存器值 * Power_LSB(1.25mW)
{
/*    uint32_t Power;
    Power = (uint32_t)((INA226_ReadReg(INA226_Power)) * 1.25);

    return Power;*/
    rt_uint16_t raw;
    if (INA226_ReadReg(INA226_Power, &raw) == RT_EOK) {
        // 处理有符号值
        rt_int16_t signed_raw = (rt_int16_t)raw;
        // 电流计算: Current = raw * current_lsb
        return signed_raw * 1.25 * 1000.0f; // 转换为
    }
    return 0.0f;
}


/* 线程入口函数 */
static void ina226_thread_entry(void *parameter)
{

     float Current, Voltage, Power;

         rt_kprintf("I2C initialized successfully.");
         INA226_Init();

         while (1)
         {
//             ShuntVoltage = INA226_GetShuntVoltage();
             rt_thread_mdelay(50);
             Voltage = INA226_GetBusVoltage();
             rt_thread_mdelay(50);
             Current = INA226_GetCurrent();
             rt_thread_mdelay(50);
             Power = INA226_GetPower();
             rt_kprintf("Voltage: %.3fV, Current: %.3fA, Power: %.3fW \n", Voltage, Current, Power);
             rt_thread_mdelay(1000); // Delay for 1 second
         }


}

int bsp_ina226_init(void)
{
    rt_thread_t tid;

    // 创建线程
    tid = rt_thread_create("ina226",
                           ina226_thread_entry,
                           RT_NULL,
                           1024,
                           RT_THREAD_PRIORITY_MAX / 2,
                           20);
    if (tid != RT_NULL) {
        rt_thread_startup(tid);
        rt_kprintf("ina226 create ok");
    }
    else {
        rt_kprintf("ina226 create off");
    }

    return 0;
}
